using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Administration;
using System.IO;
          
namespace CKS.Sandbox.Admin.Features.CKS.Sandbox.Setup
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>

    [Guid("71b63351-ae3e-4d2d-90e1-093e7a88f7f5")]
    public class CKSSandboxEventReceiver : SPFeatureReceiver
    {
        // Uncomment the method below to handle the event raised after a feature has been activated.

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            // get the current Web
            SPWeb web = SPAdministrationWebApplication.Local.Sites[0].RootWeb;

            if (web == null)
            {
                return;
            }

            #region Load Default Values into the Farm.Properties bag
            // System Settings
            SetInitialFarmProperty(Utility.GeneralSettings.ValidationEnabledProperty, "True");

            // validation behaviour
            SetInitialFarmProperty(Utility.PublicKeyTokens.FarmProperty, "Allow");
            SetInitialFarmProperty(Utility.SolutionIds.FarmProperty, "Allow");
            SetInitialFarmProperty(Utility.FileTypes.FarmProperty, "Allow");
            SetInitialFarmProperty(Utility.FileRegEx.FarmProperty, "Allow");
            SetInitialFarmProperty(Utility.FileTextString.FarmProperty, "Allow");
            SetInitialFarmProperty(Utility.AssemblyNames.FarmProperty, "Allow");
            SetInitialFarmProperty(Utility.AssemblyNameSpaces.FarmProperty, "Allow");

            // email notification
            SetInitialFarmProperty(Utility.GeneralSettings.EmailEnabledProperty, "False");
            SetInitialFarmProperty(Utility.GeneralSettings.EmailSendToFarmProperty, "");

            // save the changes
            SPFarm.Local.Update();
            #endregion

            #region Activate Feature to make sure Content Types are there
            Guid contentTypeFeatureId = new Guid("b3e3c6fb-41c1-45ef-8e16-8640b91e8c10");

            if (web.Features[contentTypeFeatureId] != null)
            {
                // remove the feature .. effectively forcing a "reactivate"
                web.Features.Remove(contentTypeFeatureId, true);
            }

            // activate the feature
            web.Features.Add(contentTypeFeatureId);
            #endregion

            // check if the list exists yet
            SPList list = null;

            try
            {
                list = web.GetList("/Lists/CKSSandboxRules");
            }
            catch (FileNotFoundException)
            {
                // means the list does not exist

                #region Create List Instance
                // Create a new list using our List Definition
                // we would use a ListInstance feature, but we need to do a few other things to it as well.
                Guid listGuid = web.Lists.Add("CKS: Sandbox - Validation Rules",
                    "Stores all of the validation rules used to validation Sandbox Solutions",
                    "Lists/CKSSandboxRules",
                    "b3e3c6fb-41c1-45ef-8e16-8640b91e8c10",
                    10074,
                    "100");

                list = web.Lists[listGuid];
                #endregion

                #region Rename columns for display
                list.Fields["Title"].Title = "Value";
                list.Fields["Title"].Description = "What is the value you want to assign to this Validation Rule?";
                list.Fields["Title"].Update();
                #endregion

                #region Set Permissions - to allow Read Only for all users
                // break inheritence on the list
                list.BreakRoleInheritance(true);

                // add a new role assignment for read-only authenticated users
                SPRoleAssignment ntAuthRoleAssignment =
                    new SPRoleAssignment("NT Authority/Authenticated Users",
                        "", "Authenticated Users", "");

                // grant the role "Read" access
                ntAuthRoleAssignment.RoleDefinitionBindings.Add(web.RoleDefinitions["Read"]);

                // add the role assignment to the list
                list.RoleAssignments.Add(ntAuthRoleAssignment);
                #endregion

                // save the changes made so far
                list.Update();
            }
            catch (Exception)
            {
                // doh!
            }

            #region Double check Content Types on list .. in the case of installing a new version
            AddContentTypeToList(list, web.AvailableContentTypes["Public Key Token"]);
            AddContentTypeToList(list, web.AvailableContentTypes["Solution ID"]);
            AddContentTypeToList(list, web.AvailableContentTypes["File Type"]);
            AddContentTypeToList(list, web.AvailableContentTypes["File RegEx"]);
            AddContentTypeToList(list, web.AvailableContentTypes["File Text String"]);
            AddContentTypeToList(list, web.AvailableContentTypes["Assembly Name"]);
            AddContentTypeToList(list, web.AvailableContentTypes["Assembly Type Namespace"]);
            #endregion


            #region Add Event Receiver to Base Content Type

            bool exists = false;
            #region ItemAdding event
            // check it doesn't already exist
            foreach (SPEventReceiverDefinition eventDef in web.AvailableContentTypes["ValidationRule"].EventReceivers)
            {
                if (eventDef.Assembly == "CKS.Sandbox.Admin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5e3bf8270d9889f7" &&
                    eventDef.Class == "CKS.Sandbox.Admin.ContentTypes.SetValidationTypeReceiver" &&
                    eventDef.Type == SPEventReceiverType.ItemAdding)
                {
                    exists = true;
                    break;
                }
            }

            if (!exists)
            {
                SPContentType cType = web.ContentTypes["ValidationRule"];
                cType.EventReceivers.Add(SPEventReceiverType.ItemAdding,
                    "CKS.Sandbox.Admin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5e3bf8270d9889f7",
                    "CKS.Sandbox.Admin.ContentTypes.SetValidationTypeReceiver");
                cType.Update(true);
            }
            #endregion

            #region ItemUpdating Event
            exists = false;
            // check it doesn't already exist
            foreach (SPEventReceiverDefinition eventDef in web.AvailableContentTypes["ValidationRule"].EventReceivers)
            {
                if (eventDef.Assembly == "CKS.Sandbox.Admin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5e3bf8270d9889f7" &&
                    eventDef.Class == "CKS.Sandbox.Admin.ContentTypes.SetValidationTypeReceiver" &&
                    eventDef.Type == SPEventReceiverType.ItemUpdating)
                {
                    exists = true;
                    break;
                }
            }

            if (!exists)
            {
                SPContentType cType = web.ContentTypes["ValidationRule"];
                cType.EventReceivers.Add(SPEventReceiverType.ItemUpdating,
                    "CKS.Sandbox.Admin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5e3bf8270d9889f7",
                    "CKS.Sandbox.Admin.ContentTypes.SetValidationTypeReceiver");
                cType.Update(true);
            }
            #endregion

            #endregion


        }

        /// <summary>
        /// Checks if a value already exists, and if not populates it
        /// </summary>
        /// <param name="PropertyKey">The property to check</param>
        /// <param name="PropertyValue">The value to provide, if null</param>
        private static void SetInitialFarmProperty(string PropertyKey, string PropertyValue)
        {
            if (SPFarm.Local.Properties[PropertyKey] == null)
            {
                SPFarm.Local.Properties[PropertyKey] = PropertyValue;
            }
        }

        private static void AddContentTypeToList(SPList list, SPContentType ct)
        {
            // Add the content type to the list.
            // note - cannot use ContentTypeId as it won't match the "List Content Type" (which uses a new ID number)
            if (ct != null && list.IsContentTypeAllowed(ct) && list.ContentTypes[ct.Name] == null)
            {
                list.ContentTypes.Add(ct);
            }
        }
    }
}
